#include <stdlib.h>
#include <string>
#include <iostream>
#include <memory>
#include <rise/common/exmacros.h>
#include <rise/common/Log.h>
#include <rise/common/Exception.h>
#include <staff/common/DataObject.h>
#include <staff-mq/client/Message.h>
#include <staff-mq/client/Subscriber.h>

std::ostream& operator<<(std::ostream& rStream, const smq::MessageHeader& rMsg)
{
  return rStream
    << "msgid: " << rMsg.sId << std::endl
    << "queue: " << rMsg.sQueue << std::endl
    << "publisher: " << rMsg.sPublisher << std::endl;
}

std::ostream& operator<<(std::ostream& rStream, const smq::Message& rMsg)
{
  return rStream
    << static_cast<const smq::MessageHeader&>(rMsg)
    << "Message: \n--\n" << rMsg.tdoMessage.ToString() << "\n--\n" << std::endl;
}

std::ostream& operator<<(std::ostream& rStream, const smq::MessageHeaderList& rlsMsgs)
{
  for (smq::MessageHeaderList::const_iterator itMsg = rlsMsgs.begin();
    itMsg != rlsMsgs.end(); ++itMsg)
  {
    rStream << "--------------------\n" << *itMsg << "--------------------\n";
  }

  return rStream;
}


int main(int nArgs, char* szArgs[])
{
  std::string sServerHost = "127.0.0.1";
  unsigned short ushServerPort = 8768;

  for (int nArg = 1; nArg < nArgs; ++nArg)
  {
    if(szArgs[nArg])
    {
      const std::string& sArg = std::string(szArgs[nArg]);
      if (sArg.substr(0, 2) == "-s")
      {
        sServerHost = sArg.substr(2);
      }
      else
      if (sArg.substr(0, 2) == "-p")
      {
        ushServerPort = static_cast<unsigned short>(atoi(sArg.substr(2).c_str()));
      }
      else
      if (sArg.substr(0, 2) == "-h")
      {
        std::cerr << "Subscriber sample.\n\n"
            << szArgs[0] << "[ -h][ -s<Server host>][ -p<port>]\n\n";
        return 0;
      }
      else
      {
        std::cerr << "unknown arg: " << sArg << "\n";
        return 1;
      }
    }
  }

  try
  {
    smq::Subscriber tSubscriber;
    tSubscriber.Init("subscriber-queueing", sServerHost, ushServerPort);


    std::string sFirstMessageId;

    { // get queues list
      smq::StringList lsQueues;

      tSubscriber.GetQueueList(lsQueues);

      std::cout << "\033[1mQueues list: \033[0m\n";
      std::cout << "--------------------\n";

      for (smq::StringList::const_iterator itQueue = lsQueues.begin();
        itQueue != lsQueues.end(); ++itQueue)
      {
        std::cout << *itQueue << std::endl;
      }

      std::cout << "--------------------\n\n";
    }

    { // get filtered queues list
      smq::StringList lsQueues;

      tSubscriber.GetFilteredQueueList("queue-*", lsQueues);

      std::cout << "\033[1mQueues list: \033[0m\n";
      std::cout << "--------------------\n";

      for (smq::StringList::const_iterator itQueue = lsQueues.begin();
        itQueue != lsQueues.end(); ++itQueue)
      {
        std::cout << *itQueue << std::endl;
      }

      std::cout << "--------------------\n\n";
    }

    { // get last message
      smq::Message tMsg;

      tSubscriber.GetLastMessage("queue-queueing", tMsg);

      std::cout << "\033[1mLastMessage: \033[0m\n" << tMsg;
    }

    { // get message headers list
      smq::MessageHeaderList lsMessageHeaders;

      tSubscriber.GetMessageHeadersList("queue-queueing", lsMessageHeaders);

      std::cout << "\n\n\033[1mMessage headers: \033[0m\n" << lsMessageHeaders;

      sFirstMessageId = lsMessageHeaders.front().sId; // saving first message id for next test
    }

    { // get first message by id
      smq::Message tMsg;

      tSubscriber.GetMessage("queue-queueing", sFirstMessageId, tMsg);

      std::cout << "\n\n\033[1mMessage by id: \033[0m\n" << tMsg;
    }

  }
  RISE_CATCH_ALL

  return 0;
}
